import md5 from 'js-md5'

/**
 * 微信App支付工具类
 * 专门用于uni-app中的App支付功能
 * 注意：生产环境中签名应该在后端计算
 */
export class WxPayUtil {
  constructor(config) {
    this.config = config || {
				appid: 'wxe281b4ec4c2ae13c', // 你的微信公众号AppID
				mch_id: '1700381946', // 你的商户号
				key: '79c16a13e46c56bc73d937cc5ac552ec', // API密钥（生产环境不能放前端）
				notify_url: 'https://api.aibaxing.com/server/api/wxPay/payNotify'// 支付结果通知地址
    }
  }

  /**
   * 生成随机字符串
   * @param {number} length 字符串长度，默认32位
   * @returns {string} 随机字符串
   */
  generateNonceStr(length = 32) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  }

  /**
   * 生成订单号
   * @param {string} prefix 订单号前缀
   * @returns {string} 订单号
   */
  generateOrderNo(prefix = '') {
    const date = new Date()
    const year = date.getFullYear()
    const month = String(date.getMonth() + 1).padStart(2, '0')
    const day = String(date.getDate()).padStart(2, '0')
    const hour = String(date.getHours()).padStart(2, '0')
    const minute = String(date.getMinutes()).padStart(2, '0')
    const second = String(date.getSeconds()).padStart(2, '0')
    const millisecond = String(date.getMilliseconds()).padStart(3, '0')
    const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0')
    
    return `${prefix}${year}${month}${day}${hour}${minute}${second}${millisecond}${random}`
  }

  /**
   * 计算微信支付签名
   * @param {Object} params 参与签名的参数对象
   * @param {string} apiKey API密钥
   * @returns {Object} 包含签名和签名字符串的对象
   */
  calculateSign(params, apiKey) {
    try {
      // 1. 参数排序（排除sign字段和空值）
      const keys = Object.keys(params)
        .filter(key => {
          const value = params[key]
          return value !== undefined && 
                 value !== null && 
                 value !== '' && 
                 key !== 'sign'
        })
        .sort()

      // 2. 拼接字符串
      let stringA = ''
      keys.forEach((key, index) => {
        if (index > 0) stringA += '&'
        stringA += `${key}=${params[key]}`
      })

      // 3. 拼接API密钥
      const stringSignTemp = `${stringA}&key=${apiKey}`

      // 4. MD5加密并转大写
      const sign = md5(stringSignTemp).toUpperCase()

      console.log('【App支付签名计算】')
      console.log('参与签名的参数:', keys.map(key => `${key}=${params[key]}`).join('&'))
      console.log('完整签名字符串:', stringSignTemp)
      console.log('计算得到签名:', sign)

      return {
        sign,
        signString: stringSignTemp,
        sortedParams: keys.map(key => `${key}=${params[key]}`).join('&')
      }
    } catch (error) {
      console.error('签名计算错误:', error)
      throw new Error(`签名计算错误: ${error.message}`)
    }
  }

  /**
   * 准备统一下单参数（App支付专用）
   * @param {Object} orderData 订单数据
   * @returns {Object} 统一下单参数
   */
  prepareUnifiedOrderParams(orderData) {
    // 参数验证
    if (!orderData.body) {
      throw new Error('商品描述不能为空')
    }
    if (!orderData.out_trade_no) {
      throw new Error('订单号不能为空')
    }
    if (!orderData.total_fee || orderData.total_fee <= 0) {
      throw new Error('支付金额必须大于0')
    }

    // 确保金额为整数（分）
    const totalFee = parseInt(orderData.total_fee)
    if (totalFee !== Number(orderData.total_fee)) {
      console.warn(`金额 ${orderData.total_fee} 已转换为整数 ${totalFee} (单位：分)`)
    }

    const orderParams = {
      appid: this.config.appid,
      mch_id: this.config.mch_id,
      nonce_str: this.generateNonceStr(),
      body: orderData.body,
      out_trade_no: orderData.out_trade_no,
      total_fee: totalFee, // 确保为整数，单位：分
      spbill_create_ip: orderData.spbill_create_ip || '127.0.0.1',
      notify_url: orderData.notify_url || this.config.notify_url,
      trade_type: 'APP' // App支付固定为APP
    }

    // 计算签名
    const signResult = this.calculateSign(orderParams, this.config.key)
    orderParams.sign = signResult.sign

    return {
      params: orderParams,
      signInfo: signResult
    }
  }

  /**
   * 准备App支付参数
   * @param {string} prepayId 预支付交易会话标识
   * @returns {Object} App支付参数
   */
  prepareAppPayParams(prepayId) {
    if (!prepayId) {
      throw new Error('prepay_id不能为空')
    }

    const timestamp = Math.floor(Date.now() / 1000).toString()
    const nonceStr = this.generateNonceStr()
    const packageValue = 'Sign=WXPay'

    // App支付参数 https://uniapp.dcloud.net.cn/api/plugins/payment.html#%E5%BE%AE%E4%BF%A1app%E6%94%AF%E4%BB%98
    const appPayParams = {
      appid: this.config.appid,  // 微信开放平台 - 应用 - AppId
      partnerid: this.config.mch_id,     // 微信支付商户号
      prepayid: prepayId,     // 统一下单订单号
      package: packageValue,  // 固定值
      noncestr: nonceStr,     // 随机字符串
      timestamp: timestamp    // 时间戳（单位：秒）
    }

    // 计算App支付签名
    const signResult = this.calculateSign(appPayParams, this.config.key)
    appPayParams.sign = signResult.sign // 签名，这里用的 MD5/RSA 签名

    return {
      params: appPayParams,
      signInfo: signResult
    }
  }

  /**
   * 调用App支付
   * @param {Object} payParams App支付参数
   * @returns {Promise} 支付结果
   */
  async callAppPay(payParams) {
    return new Promise((resolve, reject) => {
      // #ifdef APP-PLUS
      uni.requestPayment({
        provider: 'wxpay',
        orderInfo: payParams,
        success: (res) => {
          console.log('【App支付成功】', res)
          resolve({
            success: true,
            data: res
          })
        },
        fail: (err) => {
          console.error('【App支付失败】', err)
          reject({
            success: false,
            error: err,
            message: err.errMsg || '支付失败'
          })
        }
      })
      // #endif

      // #ifndef APP-PLUS
      console.warn('当前环境不支持App支付，请在App中测试')
      reject({
        success: false,
        message: '当前环境不支持App支付，请在App中测试'
      })
      // #endif
    })
  }

  /**
   * 完整的App支付流程
   * @param {Object} orderData 订单数据
   * @returns {Promise} 支付结果
   */
  async startAppPay(orderData) {
    try {
      console.log('【开始App支付流程】')

      // 1. 生成订单号（如果没有提供）
      if (!orderData.out_trade_no) {
        orderData.out_trade_no = this.generateOrderNo('APP')
        console.log('生成订单号:', orderData.out_trade_no)
      }

      // 2. 准备统一下单参数
      const unifiedOrderResult = this.prepareUnifiedOrderParams(orderData)
      console.log('统一下单参数:', unifiedOrderResult.params)

      // 3. 调用统一下单接口（需要后端实现）
      const unifiedOrderResponse = await this.callUnifiedOrder(unifiedOrderResult.params)
      
      if (!unifiedOrderResponse.success) {
        throw new Error(`统一下单失败: ${unifiedOrderResponse.message}`)
      }

      const prepayId = unifiedOrderResponse.data.prepay_id
      console.log('获得prepay_id:', prepayId)

      // 4. 准备App支付参数
      const appPayResult = this.prepareAppPayParams(prepayId)
      console.log('App支付参数:', appPayResult.params)

      // 5. 调用App支付
      const payResult = await this.callAppPay(appPayResult.params)
      
      return {
        success: true,
        orderNo: orderData.out_trade_no,
        payResult: payResult
      }

    } catch (error) {
      console.error('【App支付流程失败】', error)
      return {
        success: false,
        message: error.message || '支付失败',
        error: error
      }
    }
  }

  /**
   * 调用统一下单接口
   * @param {Object} params 统一下单参数
   * @returns {Promise} 统一下单结果
   */
  async callUnifiedOrder(params) {
    try {
      // 实际项目中需要调用后端接口
      const response = await uni.request({
        url: 'https://your-backend-api.com/api/wxpay/unifiedorder',
        method: 'POST',
        data: params,
        header: {
          'Content-Type': 'application/json'
        }
      })

      if (response.statusCode === 200 && response.data.return_code === 'SUCCESS') {
        if (response.data.result_code === 'SUCCESS') {
          return {
            success: true,
            data: response.data
          }
        } else {
          return {
            success: false,
            message: response.data.err_code_des || response.data.return_msg
          }
        }
      } else {
        return {
          success: false,
          message: '网络请求失败'
        }
      }
    } catch (error) {
      console.error('统一下单接口调用失败:', error)
      return {
        success: false,
        message: '网络请求失败'
      }
    }
  }

  /**
   * 查询订单状态
   * @param {string} outTradeNo 商户订单号
   * @returns {Promise} 查询结果
   */
  async queryOrder(outTradeNo) {
    try {
      const queryParams = {
        appid: this.config.appid,
        mch_id: this.config.mch_id,
        out_trade_no: outTradeNo,
        nonce_str: this.generateNonceStr()
      }

      const signResult = this.calculateSign(queryParams, this.config.key)
      queryParams.sign = signResult.sign

      const response = await uni.request({
        url: 'https://your-backend-api.com/api/wxpay/orderquery',
        method: 'POST',
        data: queryParams,
        header: {
          'Content-Type': 'application/json'
        }
      })

      return {
        success: response.statusCode === 200,
        data: response.data
      }
    } catch (error) {
      console.error('查询订单失败:', error)
      return {
        success: false,
        message: '查询订单失败'
      }
    }
  }
}

// 默认导出实例
export const wxPayUtil = new WxPayUtil() 